<template>
  <a-layout style="height: 100vh;" id="components-layout-demo-custom-trigger" v-if="!openingScanner">
    <a-layout-header class="header" id="profile-layout-header">
      <a-menu
        theme="dark"
        mode="horizontal"
        :default-selected-keys="['1']"
        :style="{ lineHeight: '64px' }"
      >
        <a-menu-item key="1">
          基本信息
        </a-menu-item>
      </a-menu>
    </a-layout-header>
    <a-layout-sider v-model="collapsed" :trigger="null" collapsible id="profile-layout-sidebar">
      <div class="logo" @click="toIndexPage">
        <span>{{collapsed ? '3C' : 'CoolColdCode'}}</span>
      </div>
      <a-menu theme="dark" mode="inline" :default-selected-keys="['1']">
        <a-menu-item key="1">
          <a-icon type="user" />
          <span>基本信息</span>
        </a-menu-item>
      </a-menu>
    </a-layout-sider>
    <a-layout>
      <a-layout-header style="background: #fff; padding: 0" id="content-layout-header">
        <a-icon
          class="trigger"
          :type="collapsed ? 'menu-unfold' : 'menu-fold'"
          @click="() => (collapsed = !collapsed)"
        />
      </a-layout-header>
      <a-layout-content
        :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px'}"
      >
        <a-descriptions bordered>
          <template slot="title">
            <div class="desc-title">
              <span>用户信息</span>
              <a-icon class="scan-icon" type="scan" @click="openScan" />
            </div>
          </template>
          <a-descriptions-item label="用户头像">
            <a-avatar v-if="userInfo.avatar === null || userInfo.avatar === ''" size="large" icon="user" />
            <a-avatar v-else size="large" :src="userInfo.avatar" />
            <a-icon type="edit" class="update-avatar-button" @click="openAvatarFile"></a-icon>
          </a-descriptions-item>
          <a-descriptions-item label="UUID">
            {{userInfo.id}}
          </a-descriptions-item>
          <a-descriptions-item label="用户名">
            {{userInfo.username}}
          </a-descriptions-item>
          <a-descriptions-item label="昵称">
            {{userInfo.nickname}}
          </a-descriptions-item>
          <a-descriptions-item label="生日">
            {{userInfo.birthday}}
          </a-descriptions-item>
          <a-descriptions-item label="电子邮箱">
            {{userInfo.email}}
          </a-descriptions-item>
          <a-descriptions-item label="注册时间">
            {{registerTime}}
          </a-descriptions-item>
          <a-descriptions-item label="用户状态">
            <a-badge v-if="userInfo.status === CONSTANT.USER_STATUS.ACTIVE" status="success" text="使用中" />
            <a-badge v-else-if="userInfo.status === CONSTANT.USER_STATUS.VALIDATION" status="processing" text="待验证" />
            <a-badge v-else-if="userInfo.status === CONSTANT.USER_STATUS.FROZEN" status="default" text="冻结中" />
            <a-badge v-else-if="userInfo.status === CONSTANT.USER_STATUS.DELETED" status="error" text="已注销" />
            
            <a-button v-if="userInfo.status === CONSTANT.USER_STATUS.VALIDATION" type="link" @click="showValidationModal">验证邮箱</a-button>
          </a-descriptions-item>
          <a-descriptions-item label="设备状态">
            <a-list :data-source="onlineInfo" :split="false">
              <a-list-item slot="renderItem" slot-scope="item, index">
                <a-badge status="processing" :text="item.device + ' (登录时间: ' + formatTime(item['loginTime']) + ')'"></a-badge>
                <a-popconfirm
                  :title="`确定将登录该账号的${item.device}设备踢下线吗？`"
                  ok-text="确定"
                  cancel-text="取消"
                  @confirm="handleKickOut(item.device)"
                >
                  <a-button type="link" v-if="!item['myself']">下线客户端</a-button>
                </a-popconfirm>
              </a-list-item>
            </a-list>
          </a-descriptions-item>
          <a-descriptions-item label="账户操作">
            <a-button type="link" @click="handleLogout">退出登录</a-button>
          </a-descriptions-item>
        </a-descriptions>
      </a-layout-content>
    </a-layout>

    <a-modal
      :title="validationModalTitle"
      :visible="isShowValidationModal"
      @ok="handleClickValidationOk"
      :okText="validationOkText"
      cancelText="取消"
      :confirm-loading="validationSending"
      @cancel="handleCancelValidation"
    >
      <p v-if="validationStep === 0">
        点击确认，将发送邮箱到
        <b>{{userInfo.email}}</b>
        ，注意查收验证码，5分钟之内有效
      </p>
      <a-form v-else-if="validationStep === 1" :label-col="{span: 6}" :wrapper-col="{ span: 18 }">
        <a-form-item v-else-if="" label="请输入验证码" :required="true">
          <a-input v-model="validationCode"></a-input>
        </a-form-item>
      </a-form>
    </a-modal>
    
    <input type="file" style="display: none" ref="refFile" @change="qrcodeSelected">

    <input type="file" style="display: none" ref="avatarFile" @change="avatarFileChanged">
    
  </a-layout>
  <qr-code-scanner v-else @handleClose="closeScanner" @handleDecode="handleDecode" />
</template>

<script>
import CONSTANT from '@/utils/constant'
import QrCode from 'qrcode-decoder'
import moment from 'moment'
import QrCodeScanner from "../../components/QrCodeScanner";

export default {
  name: "index",
  components: {
    QrCodeScanner
  },
  data: _ => ({
    collapsed: false,
    userInfo: {},
    
    onlineInfo: [],
    isShowValidationModal: false,
    validationStep: 0,
    validationModalTitle: '发送确认',
    validationOkText: '发送',
    validationCode: '',
    validationSending: false,

    scanLoginModalTitle: '扫码结果',
    isShowScanLoginModal: false,
    
    openingScanner: false,
    CONSTANT,
  }),
  filters: {
    // formatTime (time) {
    //   return new moment(time).format('yyyy-MM-DD HH:mm:ss')
    // }
  },
  computed: {
    registerTime() {
      if (this.userInfo['registerTime']) {
        return new moment(this.userInfo['registerTime']).format('yyyy-MM-DD HH:mm:ss')
      }
      return null
    }
  },
  methods: {
    toIndexPage () {
      this.$router.push('/').then(_ => {}).catch(_ => {})
    },
    async handleKickOut (device) {
      try {
        let {data} = await this.$http.post(`/user/kickOut?device=${device}`)
        let index = this.onlineInfo.findIndex(item => item.device === device)
        this.onlineInfo.splice(index, 1)
        this.$message.success(data.msg)
      } catch ({data}) {
        this.$message.error(data.msg)
      }
    },
    formatTime (time) {
      return new moment(time).format('yyyy-MM-DD HH:mm:ss')
    },
    openAvatarFile () {
      this.$refs['avatarFile'].dispatchEvent(new MouseEvent('click'))
    },
    async updateUser (newUserInfo) {
      try {
        let {data} = await this.$http.post('/user/update', newUserInfo)
        this.$message.success(data.msg)
      } catch ({data}) {
        this.$message.error(data.msg)
        throw data
      }
    },
    avatarFileChanged () {
      let files = this.$refs['avatarFile'].files
      if (files !== null && files.length > 0) {
        let file = files[0]
        let kb = file.size / 1024
        if (kb > 10) {
          this.$message.error('所选图片不能大于10kb')
          return
        }
        let reader = new FileReader()
        reader.addEventListener('load', _ => {
          let {id} = this.userInfo
          let avatar = reader.result
          try {
            this.updateUser({id, avatar})
            this.userInfo['avatar'] = avatar
          } catch (e) {}
        })
        reader.readAsDataURL(file)
      }
    },
    async handleLogout () {
      try {
        let {data} = await this.$http.post('/logout')
        this.$message.success('退出登录成功')
        localStorage.removeItem('token')
        this.$router.push('/').then(r => {})
      } catch ({data}) {
        this.$message.error(data.msg)
      }
    },
    closeScanner () {
      this.openingScanner = false
    },
    async handleDecode (content) {
      this.$message.success('扫描二维码完成').then(r => {})
      this.openingScanner = false
      let {data: respData} = await this.$http.post(content)
      this.$confirm({
        title: '确认登录',
        content: `扫码成功，是否确认登录${respData.data['waitingDevice']}设备？`,
        okText: '确认',
        cancelText: '取消',
        onOk: _ => {
          return new Promise((resolve, reject) => {
            this.$http.post(`/login/qrLoginPermit?key=${respData.data['key']}`).then(res => {
              this.$message.success(res.data.msg)
              resolve()
            })
          })
        },
        onCancel() {},
      })
    },
    async qrcodeSelected () {
      try {
        this.$message.info("正在扫描二维码...")
        let files = this.$refs['refFile'].files
        if (files !== null && files.length > 0) {
          let file = files[0]
          let url = window.webkitURL.createObjectURL(file)
          let qrCode = new QrCode()
          let {data: targetUrl} = await qrCode.decodeFromImage(url)
          this.$message.success("文件二维码扫码完成")
          this.handleDecode(targetUrl)
        }
      } catch (err) {
        this.$message.error('解析二维码错误')
      }
    },
    openScan () {
      this.openingScanner = true
      // this.$refs['refFile'].dispatchEvent(new MouseEvent('click'))
    },
    handleCancelValidation () {
      this.isShowValidationModal = false
    },
    async handleClickValidationOk () {
      try {
        if (this.validationStep === 0) {
          this.validationSending = true
          let {data} = await this.$http.post('/user/sendValidationCode')
          this.$message.success(data.msg)
          
          this.validationSending = false
          this.validationStep = 1
        } else if (this.validationStep === 1) {
          this.validationSending = true
          let {data} = await this.$http.post(`/user/checkValidationCode?code=${this.validationCode}`)
          this.$message.success(data.msg)

          this.validationSending = false
          this.isShowValidationModal = false
          this.userInfo.status = CONSTANT.USER_STATUS.ACTIVE
        }
      } catch ({data}) {
        this.validationSending = false
        this.$message.error(data.msg)
      }
    },
    showValidationModal () {
      this.validationStep = 0
      this.isShowValidationModal = true
    },
    async getUserInfo () {
      try {
        let {data: userInfoData} = await this.$http.get('/user')
        this.userInfo = userInfoData.data
        let {data: onlineInfoData} = await this.$http.get('/user/online')
        this.onlineInfo = onlineInfoData.data
      } catch ({data}) {
        this.$message.error(data.msg)
      }
    }
  },
  mounted() {
    this.getUserInfo()
  },
  watch: {
    validationStep (step) {
      switch (step) {
        case 0:
          this.validationModalTitle = '发送确认'
          this.validationOkText = '发送'
          break
        case 1:
          this.validationModalTitle = '验证码输入'
          this.validationOkText = '确认'
          break
        default:
          break
      }
    }
  }
}
</script>

<style scoped lang="less">
#components-layout-demo-custom-trigger {
  .trigger {
    font-size: 18px;
    line-height: 64px;
    padding: 0 24px;
    cursor: pointer;
    transition: color 0.3s;
    &:hover {
      color: #1890ff;
    }
  }
  .logo {
    height: 32px;
    margin: 16px;
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 24px;
    color: white;
    user-select: none;
    cursor: pointer;
  }
}

.desc-title {
  display: flex;
  justify-content: space-between;
}

.update-avatar-button {
  margin-left: 12px;
  cursor: pointer;
  &:hover {
    color: #1890ff;
  }
}

@media (max-width: 992px) {
  #components-layout-demo-custom-trigger {
    flex-direction: column;
  }
  #profile-layout-sidebar {
    display: none;
  }
  #content-layout-header {
    display: none;
  }
  .desc-title {
    .scan-icon {
      opacity: 1;
      font-size: 1.5rem;
    }
  }
}

@media (min-width: 992px) {
  #components-layout-demo-custom-trigger {
    flex-direction: row;
  }
  #profile-layout-header {
    display: none;
  }
  #content-layout-header {
    display: block;
  }
  .scan-icon {
    opacity: 0;
  }
}
</style>